package controller

import (
	"crawler/config"
	"crawler/engine"
	"crawler/frontend/model"
	"crawler/frontend/view"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/olivere/elastic/v7"

	"context"
	"reflect"

	"regexp"
)

// 把数据从 client 中取出来, 然后传给 view 进行渲染
type SearchResultHandler struct {
	view   view.SearchResultView
	client *elastic.Client
}

// 初始化 SearchResultHandler
func CreateSearchResultHandler(template string) SearchResultHandler {
	client, err := elastic.NewClient(
		elastic.SetURL(config.ElasticBaseUrl),
		//设置是否定期检查集群（默认为true）
		elastic.SetSniff(false))
	if err != nil {
		panic(err)
	}

	return SearchResultHandler{
		view:   view.CreateSearchResultView(template),
		client: client,
	}
}

// 处理请求 1270.0.1/search:8888?q=男士&from=0
func (h SearchResultHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	q := strings.TrimSpace(req.FormValue("q"))
	from, err := strconv.Atoi(req.FormValue("from"))
	if err != nil {
		from = 0
	}

	page, err := h.getSearchResult(q, from)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	err = h.view.Render(w, page)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
}

const pageSize = 10

func (h SearchResultHandler) getSearchResult(q string, from int) (model.SearchResult, error) {
	var result model.SearchResult
	result.Query = q

	//q := elastic.NewQueryStringQuery(rewriteQueryString(q))

	// 字段相等
	//qs := elastic.NewQueryStringQuery("Id:1195062034")

	//条件查询
	boolQ := elastic.NewBoolQuery()
	boolQ.Must(elastic.NewMatchQuery("Payload.Gender", "女士"))
	boolQ.Filter(elastic.NewRangeQuery("Payload.Age").Lt(30))
	boolQ.Filter(elastic.NewRangeQuery("Payload.Height").Gt(165))

	resp, err := h.client.
		Search(config.ElasticIndex).
		Query(boolQ).
		From(from).
		Size(pageSize).
		Do(context.Background())
	fmt.Printf("es resp: %v, q:%v\n", resp, rewriteQueryString(q))
	if err != nil {
		return result, err
	}

	result.Hits = resp.TotalHits()
	result.Start = from
	//反射
	result.Items = resp.Each(reflect.TypeOf(engine.Item{}))
	if result.Start == 0 {
		result.PrevFrom = -1
	} else {
		result.PrevFrom = (result.Start - 1) / pageSize * pageSize
	}

	result.NextFrom = result.Start + len(result.Items)
	return result, nil
}

// rewriteQueryString 重写查询字符串
// 如用户要查询年龄小于 30 岁的, 要使用 Payload.Age:(<30), 则可简化为输入：Age:(<30)
func rewriteQueryString(q string) string {
	re := regexp.MustCompile(`([A-Z][a-z]*):`)
	return re.ReplaceAllString(q, "Payload.$1:")
}
